import { Direction } from "@/constants/constants";
import { Ref } from "vue";

export type DivDom = HTMLDivElement | undefined;
export class DropdownModel {

  isOpen = false

  left = 0

  top = 0

  minWidth = 0;
  minHeight = 0

  dom?: HTMLDivElement

  scrollHandler?: Function

  width = 0

  height = 0
  hideOnScroll = false

  menuStyle= { left: '', top: '', zIndex: 0 }

  dropItemDom?: Ref<DivDom>

  // observer?:MutationObserver
  // observeConfig = { attributes: true, childList: true, subtree: true }

  toggelOpen() {
    this.isOpen = !this.isOpen;
    if (this.isOpen) {
      this.setBounds();
      this.observeScroll();
    } else {
      this.cancelObserve();
    }
  }
  open() {
    this.isOpen = true;
    this.setBounds();
    this.observeScroll();
  }

  close() {
    this.isOpen = false;
    this.cancelObserve();
  }

  onScroll() {

    if (this.hideOnScroll) {
      this.close();
    } else {
      this.setBounds();

    }
  }

  setBounds() {
    if (!this.dom) return;
    let clientRect = this.dom.getBoundingClientRect();
    //
    this.top = clientRect.top;
    this.left = clientRect.left;
    this.width = clientRect.width;
    this.height = clientRect.height;

  }

  updateMenuStyle(dropItemDom?: DivDom, maxHeight?: number, placement?: Direction, maxWidth?: number) {
    const pos =  Object.assign(
      {
        zIndex: 2000,
        maxHeight: (maxHeight || 300) + 'px',
        minWidth: this.width + 'px',
        maxWidth: maxWidth + 'px'
      },
      this.getAbsPosition(placement || Direction.BOTTOM, dropItemDom || this.dropItemDom as any)
    );
    this.menuStyle = pos;
    return pos;
  }

  observeScroll() {
    if (!this.dom) return;
    this.cancelObserve();
    this.scrollHandler = this.onScroll.bind(this);
    document.getElementById('app')?.addEventListener('scroll', this.scrollHandler as any, true);
  }

  getAbsPosition(position: Direction, dropItemDom: DivDom) {
    const windowWidth = window.innerWidth;
    const windowHeight = window.innerHeight;
    let left =  this.left;
    const dropdownMenuBounds = dropItemDom ?
      dropItemDom.getBoundingClientRect()
      :
      {
        width: 0,
        height: 0
      };
    if (position === 'bottom') {
      if (left + dropdownMenuBounds.width + 20 > windowWidth){
        left = windowWidth - (dropdownMenuBounds.width + 20);
      }
    }
    const pos = {
      left: {
        top: this.top + 'px',
        left: this.left - dropdownMenuBounds.width + 'px'
      },
      right: {
        top: this.top + 'px',
        left: this.left + this.width + 'px'
      },
      top: {
        top: this.top - dropdownMenuBounds.height + 'px',
        left: left + 'px'
      },
      bottom: {
        top: this.top + this.height + 'px',
        left: left + 'px'
      }
    }[position];
    return pos;
  }

  cancelObserve() {
    document.getElementById('app')?.removeEventListener('scroll', this.scrollHandler as any, true);
    this.scrollHandler = undefined;
  }

  destroy() {
    this.close();
    this.dom = undefined;
  }
}
